<!DOCTYPE html>
<html>
<head>
    <title>04.11 - Reflections with dynamic cubemap</title>
    <script src="../libs/three.js"></script>
    <script src="../libs/dat.gui.min.js"></script>
    <script src="../libs/OrbitControls.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<script>
    // global variables
    var renderer;
    var scene;
    var camera, cubeCamera;

    var control;
    var orbit;

    var sphere;

    function init() {

        // create a scene, that will hold all our elements such as objects, cameras and lights.
        scene = new THREE.Scene();

        // create a camera, which defines where we're looking at.
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);

        orbit = new THREE.OrbitControls(camera);

        // create a render, sets the background color and the size
        renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0x000000, 1.0);
        renderer.setSize(window.innerWidth, window.innerHeight);
        //引入六面的图片
        var urls = [
            'http://10.1.26.29:84/assets/cubemap/car/right.png',
            'http://10.1.26.29:84/assets/cubemap/car/left.png',
            'http://10.1.26.29:84/assets/cubemap/car/top.png',
            'http://10.1.26.29:84/assets/cubemap/car/bottom.png',
            'http://10.1.26.29:84/assets/cubemap/car/front.png',
            'http://10.1.26.29:84/assets/cubemap/car/back.png'
        ];

        // create the cubemap ，纹理加载
        var cubemap = THREE.ImageUtils.loadTextureCube(urls);
        cubemap.format = THREE.RGBFormat;

        // create a custom shader
        //一个特别的着色器（Three.ShaderLib[“cube”]）,结合THREE.ShaderMaterial类，我们可以基于CubeMap对象创建一个环境
        var shader = THREE.ShaderLib["cube"];
        shader.uniforms["tCube"].value = cubemap;

        //ShaderMaterial创建自己的着色器，要使用ShaderMaterial，必须传入两个着色器：fragmentShader，vertexShader
        var material = new THREE.ShaderMaterial({
            fragmentShader: shader.fragmentShader,   //定义每个传入的像素的颜色
            vertexShader: shader.vertexShader,      //允许你修改每一个传入的顶点的位置
            uniforms: shader.uniforms,              //该属性可以向你的着色器发送消息，将同样的消息发送到每个顶点和片段
            depthWrite: true,
            side: THREE.DoubleSide

        });

        // create the skybox
        var skybox = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), material);
        scene.add(skybox);

        cubeCamera = new THREE.CubeCamera(0.1, 20000, 256);
        cubeCamera.renderTarget.minFilter = THREE.LinearMipMapLinearFilter;
        scene.add(cubeCamera);

        // create a sphere and add to scene
        var sphereGeometry = new THREE.SphereGeometry(4, 15, 15);
        var cubeGeometry = new THREE.BoxGeometry(5, 5, 5);
        var cylinderGeometry = new THREE.CylinderGeometry(2, 4, 10, 20, 20, false);
        //envMap 设置环境贴图,默认是null
        var dynamicEnvMaterial = new THREE.MeshBasicMaterial({envMap: cubeCamera.renderTarget, side: THREE.DoubleSide});
        var envMaterial = new THREE.MeshBasicMaterial({envMap: cubemap, side: THREE.DoubleSide});

        sphere = new THREE.Mesh(sphereGeometry, dynamicEnvMaterial);
        sphere.name = 'sphere';
        scene.add(sphere);

        var cylinder = new THREE.Mesh(cylinderGeometry, envMaterial);
        cylinder.name = 'cylinder';
        scene.add(cylinder);
        cylinder.position.set(10, 0, 0);
        
        var cube = new THREE.Mesh(cubeGeometry, envMaterial);
        cube.name = 'cube';
        scene.add(cube);
        cube.position.set(-10, 0, 0);

        // position and point the camera to the center of the scene
        camera.position.x = 0;
        camera.position.y = 5;
        camera.position.z = 33;
        camera.lookAt(scene.position);

        // add the output of the renderer to the html element
        document.body.appendChild(renderer.domElement);

        control = new function () {
            this.rotationSpeed = 0.005;
            this.scale = 1;
        };
        addControls(control);
        render();
    }

    function addControls(controlObject) {
        var gui = new dat.GUI();
        gui.add(controlObject, 'rotationSpeed', -0.1, 0.1);
    }

    function render() {
        sphere.visible = false;
        cubeCamera.updateCubeMap(renderer, scene);
        sphere.visible = true;

        renderer.render(scene, camera);

        scene.getObjectByName('cube').rotation.x += control.rotationSpeed;
        scene.getObjectByName('cube').rotation.y += control.rotationSpeed;
        scene.getObjectByName('cylinder').rotation.x += control.rotationSpeed;

        requestAnimationFrame(render);
    }

    window.onload = init;

</script>
<body>
</body>
</html>
